package com.seanliao.nav.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.seanliao.nav.common.domain.dto.RoleDTO;
import com.seanliao.nav.common.domain.vo.RoleVO;
import com.seanliao.nav.common.exception.BusinessException;
import com.seanliao.nav.entity.SysRole;
import com.seanliao.nav.entity.SysRolePermission;
import com.seanliao.nav.entity.SysUserRole;
import com.seanliao.nav.mapper.SysRoleMapper;
import com.seanliao.nav.service.ISysRolePermissionService;
import com.seanliao.nav.service.ISysRoleService;
import com.seanliao.nav.service.ISysUserRoleService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author Sean_Liao
 * @since 2024-01-23
 */
@Service
@RequiredArgsConstructor
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    private final ISysUserRoleService SysUserRoleService;
    private final ISysRolePermissionService rolePermissionService;

    @Override
    public List<RoleVO> listAll() {
        List<SysRole> roles = this.list(new LambdaQueryWrapper<SysRole>().orderByAsc(SysRole::getSort, SysRole::getId));
        return roles.stream().map(role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtil.copyProperties(role, roleVO);
            return roleVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<RoleVO> listByUserId(Long userId) {
        List<SysUserRole> SysUserRoleList = SysUserRoleService.list(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        if (SysUserRoleList.isEmpty()) {
            return new ArrayList<>();
        }
        List<Long> roleIds = SysUserRoleList.stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        List<SysRole> roles = this.listByIds(roleIds);
        return roles.stream().map(role -> {
            RoleVO roleVO = new RoleVO();
            BeanUtil.copyProperties(role, roleVO);
            return roleVO;
        }).collect(Collectors.toList());
    }

    @Override
    public void add(RoleDTO roleDTO) {
        Assert.isFalse(this.count(new LambdaQueryWrapper<SysRole>().eq(SysRole::getName, roleDTO.getName())) > 0,
                () -> new BusinessException("角色名称已存在"));
        Assert.isFalse(this.count(new LambdaQueryWrapper<SysRole>().eq(SysRole::getCode, roleDTO.getCode())) > 0,
                () -> new BusinessException("角色标识已存在"));
        SysRole role = new SysRole();
        // TODO 雪花id
        role.setId(roleDTO.getId() == null ? IdUtil.getSnowflakeNextId() : roleDTO.getId());
        role.setName(roleDTO.getName());
        role.setCode(roleDTO.getCode());
        role.setDescription(roleDTO.getDescription());
        role.setIsBan(false);
        role.setSort(roleDTO.getSort());
        this.save(role);
    }

    @Override
    public void edit(RoleDTO roleDTO) {
        if (roleDTO.getName() != null) {
            Assert.isFalse(this.count(new LambdaQueryWrapper<SysRole>()
                            .eq(SysRole::getName, roleDTO.getName())
                            .ne(SysRole::getId, roleDTO.getId())
                    ) > 0, () -> new BusinessException("角色名称已存在"));
        }
        if (roleDTO.getCode() != null) {
            Assert.isFalse(this.count(new LambdaQueryWrapper<SysRole>()
                            .eq(SysRole::getCode, roleDTO.getCode())
                            .ne(SysRole::getId, roleDTO.getId())
                    ) > 0, () -> new BusinessException("角色标识已存在"));
        }
        SysRole role = new SysRole();
        role.setId(roleDTO.getId());
        role.setName(roleDTO.getName());
        role.setCode(roleDTO.getCode());
        role.setDescription(roleDTO.getDescription());
        role.setIsBan(roleDTO.getIsBan());
        role.setSort(roleDTO.getSort());
        this.updateById(role);
    }

    @Override
    public void remove(Long roleId) {
        Assert.isFalse(SysUserRoleService.count(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId)) > 0,
                () -> new BusinessException("角色已分配，不可删除"));
        Assert.isFalse(rolePermissionService.count(new LambdaQueryWrapper<SysRolePermission>().eq(SysRolePermission::getRoleId, roleId)) > 0,
                () -> new BusinessException("角色拥有权限，不可删除"));
        this.removeById(roleId);
    }

    @Override
    public void editUserRole(Long userId, List<Long> roleIds) {
        // 删
        SysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, userId));
        // 增
        List<SysUserRole> addList = roleIds.stream().map(roleId -> {
            SysUserRole sysUserRole = new SysUserRole();
            sysUserRole.setRoleId(roleId);
            sysUserRole.setUserId(userId);
            return sysUserRole;
        }).collect(Collectors.toList());
        SysUserRoleService.saveBatch(addList);
    }

    @Override
    public void editRoleUser(Long roleId, List<Long> userIds) {
        // 删
        SysUserRoleService.remove(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getRoleId, roleId));
        // 增
        List<SysUserRole> addList = userIds.stream().map(userId -> {
            SysUserRole userRole = new SysUserRole();
            userRole.setRoleId(roleId);
            userRole.setUserId(userId);
            return userRole;
        }).collect(Collectors.toList());
        SysUserRoleService.saveBatch(addList);
    }

    @Override
    public void sort(List<RoleDTO> roleDTOList) {
        List<SysRole> roleList = roleDTOList.stream()
                .map(roleDTO -> {
                    SysRole sysRole = new SysRole();
                    sysRole.setId(roleDTO.getId());
                    sysRole.setSort(roleDTO.getSort());
                    return sysRole;
                })
                .collect(Collectors.toList());
        this.updateBatchById(roleList);
    }

}
